package com.zeng.configuration.microprofile.config;

import com.zeng.configuration.microprofile.config.converter.Converters;
import com.zeng.configuration.microprofile.config.source.ConfigSources;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigValue;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.eclipse.microprofile.config.spi.Converter;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * @author zyb
 * @date 2021-03-14 13:36
 */
public class DefaultConfig implements Config {
    private final ConfigSources configSources;
    private final Converters converters;

    public DefaultConfig(ConfigSources configSources, Converters converters) {
        this.configSources = configSources;
        this.converters = converters;
    }


    @Override
    public <T> T getValue(String propertyName, Class<T> propertyType) {
        Optional<Converter<T>> converter = getConverter(propertyType);
        if (converter.isPresent()) {
            Converter<T> tConverter = converter.get();
            for (ConfigSource configSource : configSources) {
                String sourceValue = configSource.getValue(propertyName);
                if (sourceValue != null) {
                    return tConverter.convert(sourceValue);
                }
            }
        }
        return null;
    }

    @Override
    public ConfigValue getConfigValue(String propertyName) {
        return null;
    }

    @Override
    public <T> Optional<T> getOptionalValue(String propertyName, Class<T> propertyType) {
        return Optional.ofNullable(getValue(propertyName, propertyType));
    }

    @Override
    public Iterable<String> getPropertyNames() {
        return StreamSupport.stream(configSources.spliterator(), false)
                .map(ConfigSource::getPropertyNames)
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());
    }

    @Override
    public Iterable<ConfigSource> getConfigSources() {
        return configSources;
    }

    @Override
    public <T> Optional<Converter<T>> getConverter(Class<T> forType) {
        List<Converter<?>> converters = this.converters.getConverters(forType);
        if(converters==null||converters.isEmpty()){
            return Optional.empty();
        }
        return Optional.ofNullable((Converter<T>)converters.get(0));
    }

    @Override
    public <T> T unwrap(Class<T> type) {
        return null;
    }
}
